/*
 * analog.c
 *
 * Created: 2012-07-23 12:25:39
 *  Author: Antrykot
 */ 
#include "main.h"
#include "utils.h"
#include "analog.h"
#include "trans-k.h"
#include "sc-k.h"
#include "digital.h"
#include "../sc-k/SWLcd.h"

u16 freq = 5400;
u8 wait_spec = 0;
u8 in_kalib = 0;
u8 empty_buffer = 0;


u16 measurment = (1 << 14);

u16 fnum1,fnum2,fnum3;
u8 asknum;

u16 alfreq[8];

u8 uw_alarms = 0;

u8 akal_ask = 0;

u16 debug_alarms = 0;


#if defined(MEDIA_CH4) || defined(MEDIA_CO2)
void calc_freq()
{
	LY_OFF;

	if (wait_spec)
		return;
		
	if (in_kalib)
	{
		freq = 3000;
		return;
	}		
	/*	
	if (measurment == EMPTY_BUFFER)
	{
		LY_ON;	 
		freq = 10240;
		return;
	}		
	*/	
	
	
	u16 old_freq = freq;
	static u8 err = 0;
		
	u16 pom = measurment;
	
	if (pom & 0x8000)	// 15bit - high
	{
		pom &= 0x7FFF;
		
		if (pom & 0x2000)	// minus
		{
			pom &= 0x0FFF;
			
			if (pom < 15)
			{
				pom = 0;
			}			
			freq = 10200;
			return;
		}
		float tmp = pom * 1.5 + 10500;
		if (tmp > 12000)
		{
			err++;
			if (err > 3)
			{
				tmp = 12200;	
			}
			else
			{
				tmp = old_freq;
			}
		}
		else
			err = 0;		
		freq = tmp;
		return;
	}
	if (pom & 0x4000)	//14bit
	{
		pom &= 0x1FFF;
		if (pom & 0x1000)	//minus - 12bit
		{
			pom &= 0x0FFF;
			if (pom <= 10)		// < -0.10%
			{
				freq = 9991;
				return;
			}
			if (pom <= 20)	// 0.10-0.20%
			{
				freq = 10050;
				return;
			}
			freq = 10200;
			return;
		}
		freq = 9991 - (pom * 10);
		if (freq < 5000)
		{
			err++;
			if (err > 3)
			{
				freq = 4800;
			}
			else
			{
				freq = old_freq;
			}
		}
		else
		{
			err = 0;
		}		
		return;
	}
	
	//freq = 4500;		// ERROR ?
}

#endif

void set_freq()
{
	
	float v1 = 10000000 / freq;
	u16 v2 = v1 / (float)1000; 

	u8 F_t = v2;

	v2 = F_t * 1000;
	v1 = v1 - v2;
	v2 = v1 / 100;
	u8 F_s = v2;

	v2 = F_s * 100;
	v1 = v1 - v2;
	v2 = v1 / 10;
	u8 F_d = v2;

	v2 = F_d * 10;
	v1 = v1 - v2;
	u8 F_j = v1;

	cli();		// atomic instruction
	PORTA = 0;
	PORTC = 0;

	
	PORTA |= (( F_t & (1 << 0)) >> 0) << 6;				// A6 - ft.0	j2
	PORTA |= (( F_t & (1 << 1)) >> 1) << 7;				// A7 - ft.1	j3
	
	PORTA |= (( F_j & (1 << 0)) >> 0) << 5;				// A5 - fj.0	j5
	PORTA |= (( F_j & (1 << 1)) >> 1) << 4;				// A4 - fj.1	j6
	PORTA |= (( F_j & (1 << 2)) >> 2) << 3;				// A3 - fj.2	j7
	PORTA |= (( F_j & (1 << 3)) >> 3) << 2;				// A2 - fj.3	j8
	
	PORTA |= (( F_d & (1 << 0)) >> 0) << 1;				// A1 - fd.0	j9
	PORTA |= (( F_d & (1 << 1)) >> 1) << 0;				// A0 - fd.0	j10
	PORTC |= (( F_d & (1 << 2)) >> 2) << 2;				// C2 - fd.0	j11
	PORTC |= (( F_d & (1 << 3)) >> 3) << 3;				// C3 - fd.0	j12
	
	PORTC |= (( F_s & (1 << 0)) >> 0) << 4;				// C4 - fd.0	j13
	PORTC |= (( F_s & (1 << 1)) >> 1) << 5;				// C5 - fd.0	j14
	PORTC |= (( F_s & (1 << 2)) >> 2) << 6;				// C6 - fd.0	j15
	PORTC |= (( F_s & (1 << 3)) >> 3) << 7;				// C7 - fd.0	j16
	

	sei();

}

#define PILOTUS	245

void pilot()
{
	u8 acc = 0;
	
	//for (u16 c = 0; c < 809; c++)
	for (u16 c = 0; c < 820; c++)
	{
		if (PINB & (1 << 2))
		{
			if (acc == 1)
			{
				if (akal_ask == KAL_ASKED)
				{
					akal_ask = KAL_ACC;
					ts_data = 0;
					TS(K_ADDR_ACCEPT,0,3);
					in_kalib = 1;
				}			
			}
			acc++;
		}
		
		PILOT_LOW;
		WAITUS(PILOTUS);
		PILOT_HIGH;
		WAITUS(PILOTUS);
	}
}


void gen_long_pilot()
{
	u16 wait = 0;
	while(!ASKING)
	{
		wait++;
		if (wait > 4400)		// 2.2s
		{
			PILOT_HIGH;
			return;
		}
		PILOT_LOW;
		WAITUS(PILOTUS);
		PILOT_HIGH;
		WAITUS(PILOTUS);
	}
}

u8 respond()
{
	if (!asknum)
	{
		asknum ++;
		return 0;
	}
	
	switch (asknum)
	{
		case 1:
		{
			asknum++;	// pilot
			return 1;
			break;
		}
		case 2:
		{
			freq = fnum1;
			
			set_freq();
			asknum++;
			return 3;
		}
		case 3:
		{
			freq = fnum2;
			
			set_freq();
			asknum++;
			return 3;
		}
		case 4:
		{
			freq = fnum3;

			set_freq();
			asknum++;
			return 3;
		}
		case 5:
		{
			wait_spec = 0;
			calc_freq();
			set_freq();
			asknum = 6;
			empty_buffer = 1;
			return 2;
		}
		
		case 6:
		{
			// normal or special
			
			//wait_spec = 0;
			asknum = 6;
			
			if (wait_spec)
			{
				set_freq();
				wait_spec = 0;
				return 2;
			}

			if (akal_ask == KAL_ASKED)
			{
				in_kalib = 0;
				wait_spec = 0;
				calc_freq();
				set_freq();
				return 2;
			}
			
			if (akal_ask == KAL_ASK)
			{
				akal_ask = KAL_ASKED;
				freq = 3000;
				set_freq();
				return 2;
			}
			if (akal_ask == KAL_FINISHOK || akal_ask == KAL_FINISHERR)
			{
				if (akal_ask == KAL_FINISHOK)
				{
					freq = 3500;
				}
				else
				{
					freq = 4000;
				}
				akal_ask = 0;
				in_kalib = 0;
				wait_spec = 0;
				asknum = 6;
				set_freq();
				return 2;
			}

			calc_freq();
			set_freq();
			asknum = 6;
			empty_buffer = 1;
			wait_spec = 0;
			return 2;
		}
	}
	
	return 0;
	
}

void calc_num()
{
	   
	fnum1 = nr & 0x0F;
	fnum2 = (nr & 0xF0) >> 4;
	fnum3 = (nr & 0xF00) >> 8;
	
	fnum1 = fnum1 * 500 + 4500;
	fnum2 = fnum2 * 500 + 4500;
	fnum3 = fnum3 * 500 + 4500;
	   
}




void check_alarms()
{
	
	u8 a1 = 0, a2 = 0, a3 = 0, a4 = 0;
	
	uw_alarms = 0xFF;
	
	for (u8 c = 0; c < 5; c++)
	{
		if (alfreq[c] < 3000 && alfreq[c] > 2600)			// 2800
		{
			a4++;		// oba wybite
		}
		if (alfreq[c] < 2420 && alfreq[c] > 2050)			// 2200
		{
			a3++;		// Al1, al2 kasuje
		}
		if (alfreq[c] < 3920 && alfreq[c] > 3300)			// 3700
		{
			a2++;		// Al1, podtrzymuje
		}
		if (alfreq[c] < 1950 && alfreq[c] > 1600)			// 1800
		{
			a1++;		// kasuje oba wybicia
		}
	}
	
	if (a4 >= 3)
	{
		uw_alarms = 0x00;
	}
	if (a3 >= 3)
	{
		uw_alarms = 0x10;
	}
	if (a2 >= 3)
	{
		uw_alarms = 0x10;
	}
	if (a1 >= 3)
	{
		uw_alarms = 0x11;
	}
	
	debug_alarms = alfreq[2];
	
	//swl_setpos(16);
	//swl_printi(uw_alarms);
	//swl_print(";");
	
	if (uw_alarms == 0xFF)		// no good impuls.
		return;
	TS(K_ADDR_ALARMS,uw_alarms,3);
	INT0_DISABLE;
	//WAITMS(50);
	allow_internal_comm = 1;	// transmi it now

}


#if defined(MEDIA_PS) || defined(MEDIA_PD)
void calc_freq()
{
	LY_OFF;

	if (wait_spec)
	return;
	
	if (in_kalib)
	{
		freq = 3000;
		return;
	}
	/*
	if (measurment == EMPTY_BUFFER)
	{
		LY_ON;
		freq = 10240;
		return;
	}
	*/
	
	u16 pom = measurment;
	
		
				
	u8 m_type = (pom & 0xC000) >> 14;
	pom &= 0x3FFF;
	
	//_write(80,m_type)
	
	switch (m_type)
	{
		case  0x01:		//press absolute or diff (depend on l_range, h_range)
		{
			if (pom > h_range)
			{
				freq = 4900; 
				return;
			}
			
			if (pom < l_range)
			{
				freq = 10300;
				return;
			}
			
			float f = pom - l_range;
			f = f / (h_range - l_range);
			f = 10000 - (f * 5000);
			

			
			if (f > 10000 || f < 5000)
			{
				f = 4750;
				
			}
			freq = f;

			return;
			break;
		}
		case  0x02:		//relative humidity
		{
			if (pom > 1000)
			{
				freq = 4900;
				return;
			}
			
			float f = 10000 - pom * 5;
			if (f > 10000 || f < 5000)
			f = 4750;		// EEROR ?
			freq = f;
			return;
			break;
		}
		case 0x03:		//temp -20.0 +50
		{
			if (pom > 1000)
			{
				freq = 4900;
				return;
			}
			
			
			/////pom += 200;		/// -20 'C
			
			float f = 10000 - ((pom)/((double)(700.0)))*5000.0 ;
			write_word(120,pom);
			write_double(126,f);
			if (f > 10000 || f < 5000)
			f = 4750;		// EEROR ?
			freq = f;
			return;
			break;
			}	

		}
	
	

	
	freq = 4500;		// ERROR ?
}

#endif
